#include "Registry/Registry.h"

BEGIN_GLSX_NAMESPACE

Registry::Registry( HKEY hRoot, PCWSTR pszSubKey, REGSAM samDesired /*= KEY_ALL_ACCESS*/, bool blCreateIfNotExist /*= true*/ )
{
	GLASSERT(hRoot && pszSubKey);

	LONG nRet;

#ifndef WINCE
	if (HKEY_CURRENT_USER == hRoot)
	{
		nRet = ::RegOpenCurrentUser(KEY_ALL_ACCESS, &m_hUser);
		GLASSERT (nRet == ERROR_SUCCESS);
		hRoot = m_hUser;
	}
#endif

	if (blCreateIfNotExist)
	{
		nRet = ::RegCreateKeyExW(hRoot, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, &m_hKey, NULL);
	}
	else
	{
		nRet = ::RegOpenKeyExW(hRoot, pszSubKey, 0, samDesired, &m_hKey);
	}

	GLASSERT (nRet == ERROR_SUCCESS);
}

Registry::~Registry()
{
	if (m_hKey)
	{
		::RegCloseKey(m_hKey);
	}
#ifndef WINCE
	if (m_hUser)
	{
		::RegCloseKey(m_hUser);
	}
#endif
}

DWORD Registry::WriteBinaryValue(LPCVOID lpValue, DWORD dwLength, PCWSTR pszValueName) const
{
	return ::RegSetValueExW(m_hKey, pszValueName, 0, REG_BINARY, reinterpret_cast<const BYTE*>(lpValue), dwLength);
}

DWORD Registry::WriteDoubleWordValue(DWORD dwValue, PCWSTR pszValueName) const
{
	return ::RegSetValueExW(m_hKey, pszValueName, 0, REG_DWORD, reinterpret_cast<LPBYTE>(&dwValue), sizeof(DWORD));
}

DWORD Registry::WriteStringValue(PCWSTR pszValue, PCWSTR pszValueName) const
{
	if (!pszValue) return ERROR_INVALID_PARAMETER;

	return ::RegSetValueExW(m_hKey, pszValueName, 0, REG_SZ, reinterpret_cast<const BYTE*>(pszValue), (wcslen(pszValue) + 1) * sizeof(WCHAR));
}

DWORD Registry::ReadBinaryValue(LPVOID lpValue, DWORD dwSize, PCWSTR pszValueName, PDWORD pType) const
{
	return ::RegQueryValueExW(m_hKey, pszValueName, NULL, pType, reinterpret_cast<LPBYTE>(lpValue), &dwSize);
}

DWORD Registry::ReadDoubleWordValue(PDWORD pValue, PCWSTR pszValueName, PDWORD pType) const
{
	DWORD dwSize = sizeof(DWORD);

	return ::RegQueryValueExW(m_hKey, pszValueName, NULL, pType, reinterpret_cast<LPBYTE>(pValue), &dwSize);
}



DWORD Registry::ReadStringValue(std::wstring& strValue, PCWSTR pszValueName, PDWORD pType) const
{
	DWORD	dwSize, dwRet;
	PWSTR	pszValue;
	HANDLE	hHeap;

	// Determine data size
	dwRet = ::RegQueryValueExW(m_hKey, pszValueName, NULL, pType, NULL, &dwSize);
	if (dwRet != ERROR_SUCCESS)
		return dwRet;

	// Alloc buffer
	hHeap		= ::GetProcessHeap();
	pszValue	= reinterpret_cast<PWSTR>(::HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, dwSize + sizeof(WCHAR)));

	// Read value
	dwRet = ::RegQueryValueExW(m_hKey, pszValueName, NULL, pType, reinterpret_cast<LPBYTE>(pszValue), &dwSize);

	if (ERROR_SUCCESS == dwRet)
		strValue = pszValue;

	// Free buffer
	::HeapFree(hHeap, 0, pszValue);

	return dwRet;
}


END_GLSX_NAMESPACE
